#质检及音素统计
import sys
from check_function import *
import chardet


def detect(file,encodinglist=['utf-8','gbk','utf-16','big5','euc-jp','euc-kr','latin1'],insert=None):
    """检测文档编码格式"""
    if insert:
        pos=0
        for index,insertcode in insert:
            encodinglist.insert(index+pos,insertcode)
            pos+=1
    for e in encodinglist:
        try:
            with open(file,'r',encoding=e) as f:
                content=f.readlines()
                return e
        except:
            continue
    return None

def chardetect(file):
    """检测文档编码格式"""
    return chardet.detect(open(file,'rb').read())['encoding']

def get_encoding(filename):
    if detect(filename):
        encoding=detect(filename)
    elif chardetect(filename):
        encoding=chardetect(filename)
    else:
        encoding='utf-8'
    return encoding

#打开文件,输入地址返回全部文本
def readfile(filename,encoding):
    with open(filename, 'r', encoding=encoding) as f:
        lines = f.readlines()
    return lines

#2、重音检查，输入未分割的音标行语句，有错返回输入语句，无差错不返回
#检查1、单音节无重音 2、多音节重音1唯一且必须出现 3、多音节重音2唯一或不出现 4、重音1必须在元音后
def accent(pronline):
    for pron in pronline.split("/"):
        #print(pron)
        number = re.compile('[0-9]')
        number1 = re.compile('1')
        number2 = re.compile('2')
        if len(pron.split(".")) == 1:#检查1
            match = number.findall(pron)
            if match:
                return pron
        elif len(pron.split(".")) > 1:#检查2
            match1 = number1.findall(pron)
            if match1 != ['1']:
                return pron
            else:
                index_list = [i.start() for i in re.finditer('1', pron)]#检查4
                for j in index_list:
                    #print(pron[j], pron[j - 1])
                    if pron[j-1] not in yuan:
                        return pron
            match2 = number2.findall(pron)#检查3
            if len(match2) > 1:
                return pron
    return False

def yuanyin(pronline,yuan):#元音识别 音标行>音标>音节>音素
    pattern = re.compile(yuan)
    for i in pronline.split("/"):#i->音标
        for j in i.split("."):#j->音节
            match = pattern.findall(j)
            if set(match) == {" "}:
                return j.strip()

def yuanyin_uniq(pronline):#元音识别 音标行>音标>音节>音素
    for i in pronline.split("/"):#i->音标
        for j in i.split("."):#j->音节
            index_list = [i.start() for i in re.finditer("[aeɛioɔu]", j)]

            if len(index_list) > 1:
                return j.strip()

def yinsurate(pron):
    for i in pron.split("/"):#i->音标
        for j in i.split("."):#j->音节
            for k in j.split(" "):
                k = re.split('\d+$', k.strip())[0]
                if k == "":
                    continue
                if k in phongme:
                    if k in yinsudict:
                        yinsudict[k] += 1
                    else:
                        yinsudict[k] = 1
                else:
                    erroryinsu.add(k)
    for i in phongme:
        yinsudict.setdefault(i,0)

def duoyinzi(sent,pron):
    word = sent.split()
    yin = pron.split("/")
    for j in range(len(word)):
        duoyin.append((word[j], yin[j].strip()))

def point_spacecheck(pronline):#点左右空格检查 音标行>音标>音节>音素
    #print("pronline",pronline)
    for i in pronline.split("/"):#i->音标
        for j in i.split("."):#j->音节
            #print("ij",i,j)
            if j == i.split(".")[0]:
                if j[-1] == " ":
                    continue
            if j == i.split(".")[-1]:
                if j[0] == " ":
                    continue
            elif j[-1] == " " and j[0] == " ":
                continue
            else:
                return j.strip()

def sentlastcheck(sent):
    alphabet = ["a","à","e","è","é","i","ì","o","ò","u","ù","b","c","d","f","g","h","l","m","n","p","q","r","s","t","v","z","j","k","w","x","y"]
    pun = [",",".","?","!"]
    doublepun = [',"','."','?"','!"','".','"?','"!','».','»!','»?','\'.','\'?','\'!']
    #print(sent)
    if sent[-2:] in doublepun and sent[-3] == "%" and sent[-4] in alphabet or sent[-4] in eng:
        pass
    elif sent[-2:] not in doublepun and sent[-1] in pun and sent[-2]  == "%" and sent[-3] in alphabet or sent[-4] in eng:
        pass
    else:
        return sent


#非法音素检查
#频次统计，字典 k 音素 v 频次
#覆盖率，计算全部频次，除以单独频次
#一个单词多个发音 字典 k 单词+发音 v 频次
#建立列表，将需要写入文本的数据追加，最后一次性写入文本

sentlast = []#文本行%检测
textlen = []#文本音标长度不一致列表
textformat = []#文本空格格式检查列表
point_space = []#点左右空格
zhongyinaccent = []#音标重音检查列表
yuanyinaccent = []#元音检查列表
yuanyinuniq = []#元音不唯一列表
feifayinsu = []#非法音素列表
queshiyinsu = []#文本缺失音素
duoyin = []#词音对应
yinsudict = {}#音素频次覆盖率
erroryinsu = set()#非法音素
linenumber = 0#奇偶行，偶数文字行，奇数音标行
yuan = "[a e ɛ i o ɔ u]"#元音音素
phongme = ['a', 'e', 'ɛ', 'i', 'j', 'o', 'ɔ', 'u', 'w', 'b', 'd', 'dz', 'k', 'ʃ', 'tʃ', 't', 'ts', 'g', 'dʒ', 'ʎ', 'ɲ', 'l', 'm', 'n', 'f', 'p', 'r', 's', 'z']#全部音素
eng = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
path = sys.argv[1]

encoding=get_encoding(path)

textfile = readfile(path,encoding)

for i in range(0,len(textfile),2):
    sentlist = textfile[i].replace('\n', '').split('\t')
    num = sentlist[0]
    sent = sentlist[1].strip("%.\n")
    sent_pre = sentlist[1].strip()
    pron = textfile[i + 1].replace('\n', '').lstrip()
    yinsurate(pron)
    if end_char(sent, " ") :  # 2、检查结尾多空格
        textformat.append([num, sent])
    if end_char(pron, " "):
        textformat.append([num, pron])

    if more_space_continue(sent):  # 2、检查双空格 调用
        textformat.append([num, sent])
    if more_space_continue(pron):
        textformat.append([num, pron])
    if pronsent_num(sent, pron):  # 1、数量一致 调用
        textlen.append([num, len(sent.split()), sent, len(pron.split("/")), pron])
    else:
        duoyinzi(sent, pron)

    if accent(pron) != False:
        zhongyinaccent.append([num, accent(pron)])  # 2、重音检查
    if yuanyin(pron, yuan) != None:
        yuanyinaccent.append([num, yuanyin(pron, yuan)])  # 3、元音检查

    if yuanyin_uniq(pron) != None:
        yuanyinuniq.append([num, yuanyin_uniq(pron)])

    if point_spacecheck(pron) != None:
        point_space.append([num, point_spacecheck(pron)])

    if sentlastcheck(sent_pre) != None:
        sentlast.append([num,sentlastcheck(sent_pre)])

with open("质检工具输出结果.txt","w",encoding=encoding) as w:
    w.write("*************长度不一致**************\n\n")
    for i in textlen:
        w.write(str(i[0]))
        w.write("\n")
        w.write(str(i[1]))
        w.write("\t")
        w.write(str(i[2]))
        w.write("\n")
        w.write(str(i[3]))
        w.write("\t")
        w.write(str(i[4]))
        w.write("\n")


    w.write("\n*************重音检查**************\n\n")
    for i in zhongyinaccent:
        w.write(str(i[0]))
        w.write("\t")
        w.write(str(i[1]).strip())
        w.write("\n")


    w.write("\n*************空格不规范**************\n\n")
    for i in textformat:
        w.write(str(i[0]))
        w.write("\t")
        w.write(str(i[1]))
        w.write("\n")


    w.write("\n****************没有元音音素的音节**************\n\n")
    for i in yuanyinaccent:
        w.writelines(str(i[0]))
        w.writelines("\t")
        w.writelines(str(i[1]))
        w.write("\n")

    w.write("\n*************合法音素频次覆盖率**************\n\n")
    w.write("合法音素\t")
    w.write("频次\t")
    w.write("覆盖率\n")
    for i in phongme:
        w.write(i)
        w.write("\t")
        w.write(str(yinsudict[i]))
        w.writelines("\t")
        w.write(str((yinsudict[i])/sum(yinsudict.values())*100)+"%")
        w.write("\n")

    w.write("\n*************非法音素**************\n\n")
    w.write(str(list(erroryinsu)))
    w.write("\n\n*************缺失音素**************\n\n")
    for k,v in yinsudict.items():
        if v == 0:
            queshiyinsu.append(k)
    w.write(str(queshiyinsu))

    ziyindict = {}
    zidict = {}
    for i in duoyin:
        if i in ziyindict.keys():
            ziyindict[i] += 1
        else:
            ziyindict[i] = 1
    w.write("\n\n*************多音字**************\n\n")
    w.write("词")
    w.write("\t")
    w.write("音标")
    w.write("\t")
    w.write("频次")
    w.write("\n")
    for k,v in ziyindict.items():
        if k[0] in zidict:
            zidict[k[0]] += 1
        else:
            zidict[k[0]] = 1
    for k1,v1 in zidict.items():
        if v1 > 1:
            for k,v in ziyindict.items():
                if k1 == k[0]:
                    w.write(str(k).strip("(").strip(")"))
                    w.write("\t")
                    w.write(str(v))
                    w.write("\n")

    w.write("\n\n*************元音不唯一**************\n\n")
    for i in yuanyinuniq:
        w.writelines(str(i[0]))
        w.writelines("\t")
        w.writelines(str(i[1]))
        w.write("\n")

    w.write("\n\n*************结尾%%**************\n\n")
    for i in sentlast:
        w.write(str(i[0]))
        w.write("\t")
        w.write(str(i[1]).strip())
        w.write("\n")

    w.write("\n\n*************音节划分空格缺失**************\n\n")
    for i in point_space:
        w.writelines(str(i[0]))
        w.writelines("\t")
        w.writelines(str(i[1]))
        w.write("\n")